
// Copyright (C) 2007 Richard Uhler
// This file is part of Esiply.
//
// Esiply is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License, Version 2,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

#include "Boolean.h"
#include "Completion.h"
#include "DoWhileStatement.h"
#include "Null.h"
#include "String.h"

DoWhileStatement::DoWhileStatement(Statement* stmt, Expression* exp)
    :m_stmt(stmt), m_exp(exp)
{}

Value* DoWhileStatement::execute_internal(Scope* scope) const
{
    // Ecma 12.6.1
    // 1. Let v = empty
    // TODO: what is empty?
    Value* v = Null::null;
    Boolean* exp = NULL;
    do
    {
        // 2. Evaluate Statement
        Value* res = m_stmt->execute(scope);

        //3. if res.value is not empty, let v be res.value
        if (res->completion()->value()->getType() != VT_NULL)
        {
            v = res->completion()->value();
        }

        // 4. If res.type is continue and res.target is in the current label
        // set, go to step 7.
        if (!(res->completion()->type() == CT_CONTINUE
                && this->hasLabel(res->completion()->target())))
        {
            // 5. If result is type break and targe tis in the current
            // label set, return (normal, v, empty)
            // We don't have to do anything because Statement does it for us

            // 6. If result is an abrupt completion, return it
            if (res->completion()->type() != CT_NORMAL)
            {
                return res;
            }
        }

        // 7. Evaluate Expression
        // 8. call getValue
        // 9. call toBoolean
        exp = m_exp->evaluate(scope)->getValue()->toBoolean();

        // 10. if result is true, go to step 2.
    } while (exp->isTrue());

    // 11. Return (normal, v, empty)
    return new Completion(CT_NORMAL, v, Completion::empty);
}


void DoWhileStatement::getDeclaredVariables(std::vector<String*>& ids) const
{
    m_stmt->getDeclaredVariables(ids);
}

